package com.sunkyc.framework.exception;

import cn.dev33.satoken.exception.DisableLoginException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import com.sunkyc.commons.entity.R;
import com.sunkyc.commons.exception.CustomerException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.sql.SQLException;
import java.util.List;

/**
 * 统一异常处理
 */
@RestControllerAdvice
@Slf4j
public class GlobException {
    @ExceptionHandler(CustomerException.class)
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public R<Void> handleCustomerException(CustomerException e,
                                           HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}', 方法 '{}, '不支持'{}'请求", requestURI, request.getMethod(),e.getMessage());
        return R.fail(e.getMessage());
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public R<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder sb = new StringBuilder("非法参数:");
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        for (int i = 0; i < fieldErrors.size(); i++) {
            sb.append(fieldErrors.get(i).getDefaultMessage());
            if (i < fieldErrors.size() - 1){
                sb.append(",");
            }
        }
        return R.fail(sb.toString());
    }

    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public R<Void> handleConstraintViolationException(ConstraintViolationException ex) {
        return R.fail(ex.getMessage());
    }


    /**
     * 权限异常
     * @param
     * @return
     */

    @ExceptionHandler(NotPermissionException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public R<Void> handleNotPermissionException(NotPermissionException e,
                                           HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}', 方法 '{}, '不支持'{}'请求", requestURI, request.getMethod(),e.getMessage());
        return R.fail("您无此功能的操作权限");
    }

    /**
     * 未登录异常
     * @param
     * @return
     */
    @ExceptionHandler({NotLoginException.class})
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public R<Void> handleNotLoginException(NotLoginException ex) {
        String messgae = "未登录或登录超时，请重新登录";
        log.error(messgae);
        return R.fail(400,messgae);
    }

    /**
     * 角色异常
     * @param
     * @return
     */
    @ExceptionHandler({NotRoleException.class})
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public R<Void> handleNotRoleException(NotRoleException ex) {
        String messgae = "角色认证失败";
        log.error(messgae);
        return R.fail(403,messgae);
    }


    /**
     * 封禁异常
     * @param ex
     * @return
     */
    @ExceptionHandler({DisableLoginException.class})
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public R<Void> handleDisableLoginException(NotLoginException ex) {
        String messgae = "账号已被封禁，请联系管理员";
        log.error(messgae);
        return R.fail(401,messgae);
    }

    @ExceptionHandler({SQLException.class})
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public R<Void> handleSQLException(SQLException ex) {
        String messgae = "请求被系统拒绝";
        log.error(messgae);
        return R.fail(500,messgae);
    }


}
